package org.gap.jseed;

public interface SeedContainer {

	/**
	 * Used to determine if a key has already been bound to a service
	 * 
	 * @param key
	 *            the key used to retrieve a service
	 * @return true if the key has been bound, false otherwise
	 */
	public abstract boolean hasService(Class<?> key);

	/**
	 * Used to bind a service builder to a given key
	 * 
	 * @param <T>
	 *            defines a key type to a service builder type
	 * @param key
	 *            used to retrieve the service, cannot be null
	 * @param builder
	 *            the service builder to be bound, cannot be null
	 */
	public abstract <T> void bind(Class<T> key, Builder<? extends T> builder);

	/**
	 * Used to bind a service to a given key
	 * 
	 * @param <T>
	 *            defines a key type to a service type.
	 * @param key
	 *            used to retrieve the service, cannot be null
	 * @param service
	 *            the service to be bound, cannot be null
	 * @throws IllegalStateException
	 *             if hasService(key) returns true.
	 */
	public abstract void bind(Class<?> key, Object service);

	/**
	 * Used to bind a key to a service. The service will be instantiated upon
	 * calling the get method.
	 * 
	 * @param key
	 *            the key to bind
	 * @param service
	 *            the service class to be instantiated
	 */
	public abstract <T> void bind(Class<T> key, Class<? extends T> service);

	/**
	 * A convenience method that will take a service and have it bound to
	 * itself.
	 * 
	 * @param <T>
	 * @param bindToSelf
	 */
	public abstract <T> void register(Class<T> bindToSelf);

	/**
	 * Retrieves the service under the given key (as like a dictionary)
	 * 
	 * @param <T>
	 *            The type to be returned
	 * @param key
	 *            the lookup type
	 * @return the instance of the service bound to the key
	 */
	public abstract <T> T get(Class<T> key);

	/**
	 * Creates an instance of the class much in the same way a service is
	 * instantiated, following the rules for all registered builder factories.
	 * The instance created is not stored in the Seed container.
	 * 
	 * 
	 * @param <T>
	 *            the type that will be returned
	 * @param toCreate
	 *            the service or instance to be instantiated
	 * @return a new instance
	 */
	public abstract <T> T create(Class<T> toCreate);
}
